package com.gralves.elasticsearch.utils.aspect;

import com.gralves.elasticsearch.utils.anno.TimeStatistics;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

/**
 * @author zhouyibin
 * @date 2018/12/24
 * @desc
 */
@Slf4j
@Aspect
@Component
public class CommonAspect {

    @Pointcut("@annotation(com.gralves.elasticsearch.utils.anno.TimeStatistics))")
    public void timeStatistics() {
    }

    @Around(value = "timeStatistics()", argNames = "point")
    public Object timeAround(ProceedingJoinPoint point) {
        String serialId = UUID.randomUUID().toString();
        Signature signature = point.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        TimeStatistics timeStatistics = method.getDeclaredAnnotation(TimeStatistics.class);
        String info = "方法";
        if (null != timeStatistics) info = timeStatistics.value();
        try {
            Long startTime = System.currentTimeMillis();
            log.info(
                    ">>>>>>>>>>>>>>>>>>>>[ " +
                            "开始执行 <{}> , " +
                            "time : <{}> , " +
                            "serialId: {} " +
                            "]<<<<<<<<<<<<<<<<<<<<<",
                    info,
                    new SimpleDateFormat("yyyy-MM-dd HH-mm-ss").format(new Date()),
                    serialId
            );
            Object proceed = point.proceed();
            Long endTime = System.currentTimeMillis();
            log.info(">>>>>>>>>>>>>>>>>>>>[ " +
                    "执行 <{}> 结束, " +
                    "执行时间 : <{} ms> , " +
                    "time : <{}> , " +
                    "serialId: {} " +
                    "]<<<<<<<<<<<<<<<<<<<<<",
                    info,
                    endTime-startTime,
                    new SimpleDateFormat("yyyy-MM-dd HH-mm-ss").format(new Date()),
                    serialId
            );
            return proceed;
        } catch (Throwable throwable) {
            log.error(">>>>>>>>>>>>>>>>>>>[ <{}> 调用时间记录失败 , serialId: {} ,REASON : {} ===> COMPLETE ERROR : {} ]<<<<<<<<<<<<<<<<<", info,serialId, throwable.getMessage(), throwable.toString());
            throwable.printStackTrace();
        }
        return null;
    }
}
